﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Input;

namespace Qero.ChartPoint
{
    /// <summary> Виды табличных данных
    /// </summary>
    public enum CPTable
    {
        NotDefine = 0,
        Chart = 1,
        Field = 2
    }

    public enum QDType
    {
        NotDefine = 0,
        GUID = 1,
        TEXT = 2,
        BLOB = 3,
        BOOL = 4,
        INT = 5
    }

    public enum CFType
    {
        NotDefine = 0,
        /// <summary> Дата время
        /// </summary>
        DATE = 1,
        /// <summary> Текст (строка)
        /// </summary>
        TEXT = 2,
        /// <summary> Выбор из списка (включая булево значение)
        /// </summary>
        PICK = 3,
        /// <summary> Подбор одиночный
        /// </summary>
        LOOK = 4,
        /// <summary> Подбор множественный
        /// </summary>
        MANY = 5,
        /// <summary> Целое число
        /// </summary>
        NUMR = 6,
        /// <summary> Дробное число
        /// </summary>
        FRAC = 7
    }

    class BaseClass
    {
    }

    public class LookedDataQuark
    {
        private ValueQuark _basevalue = new ValueQuark(false);
        public ValueQuark baseValue
        {
            get { return _basevalue; }
            set { _basevalue = value; }
        }

        private List<ValueQuark> _valueset = new List<ValueQuark>();
        public List<ValueQuark> ValueSet
        {
            get { return _valueset; }
            set { _valueset = value; }
        }
    }

    public class DataQuarkLine
    {
        private string _searchname = string.Empty;

        private CPTable _datatable = CPTable.NotDefine;
        public CPTable dataTable
        {
            get { return _datatable; }
            set { _datatable = value; }
        }

        public string tableCaption
        {
            get { return string.Format("{0}er ", dataTable); }
        }

        public string FLD_Uid { get { return GetUidField(this.dataTable); } }

        public string FLD_Sub { get { return string.Format("{0}Sub", this.dataTable); } }

        public string FLD_Name { get { return string.Format("{0}Name", this.dataTable); } }

        public string FLD_Imag { get { return string.Format("{0}Imag", this.dataTable); } }

        public string FLD_Type { get { return string.Format("{0}Type", this.dataTable); } }

        public string FLD_Enum { get { return string.Format("{0}Enum", this.dataTable); } }

        public string FLD_File { get { return string.Format("{0}Files", this.dataTable); } }

        private string GetUidField(CPTable tableKind)
        {
            return string.Format("{0}Uid", tableKind);
        }

        private List<DataQuark> _lineSet = new List<DataQuark>();
        public List<DataQuark> LineSet
        {
            get { return _lineSet; }
            set { _lineSet = value; }
        }

        public List<DataQuark> SetValues()
        {
            return (from il in this.LineSet where !il.callWhere select il).ToList<DataQuark>();
        }

        public List<DataQuark> SelValues()
        {
            return (from il in this.LineSet where il.callWhere select il).ToList<DataQuark>();
        }

        public void AddUidQuark(Guid uidValue, bool isWhere)
        {
            this.LineSet.Add(new DataQuark(FLD_Uid, QDType.GUID, uidValue, isWhere));
        }

        public void AddUidQuark(Guid uidValue, bool isWhere, CPTable tableKind)
        {
            this.LineSet.Add(new DataQuark(GetUidField(tableKind), QDType.GUID, uidValue, isWhere));
        }

        public Guid GetUidQuark()
        {
            DataQuark tmpQuark = FindQuarkInSet(FLD_Uid);

            return (tmpQuark != null) ? tmpQuark.GuidValue : new Guid();
        }

        public Guid GetUidQuark(CPTable tableKind)
        {
            DataQuark tmpQuark = FindQuarkInSet(GetUidField(tableKind));

            return (tmpQuark != null) ? tmpQuark.GuidValue : new Guid();
        }

        public void AddSubQuark()
        {
            this.LineSet.Add(new DataQuark(FLD_Sub, QDType.TEXT));
        }

        public void AddSubQuark(string subValue)
        {
            this.LineSet.Add(new DataQuark(FLD_Sub, QDType.TEXT, subValue));
        }

        public string GetSubQuark()
        {
            DataQuark tmpQuark = FindQuarkInSet(FLD_Sub);

            return (tmpQuark != null) ? tmpQuark.TextValue : string.Empty;
        }

        public void AddNameQuark()
        {
            this.LineSet.Add(new DataQuark(FLD_Name, QDType.TEXT));
        }

        public void AddNameQuark(string nameValue)
        {
            this.LineSet.Add(new DataQuark(FLD_Name, QDType.TEXT, nameValue));
        }

        public string GetNameQuark()
        {
            DataQuark tmpQuark = FindQuarkInSet(FLD_Name);

            return (tmpQuark != null) ? tmpQuark.TextValue : string.Empty;
        }

        public void AddImagQuark()
        {
            this.LineSet.Add(new DataQuark(FLD_Imag, QDType.BLOB));
        }

        public void AddFileQuark()
        {
            this.LineSet.Add(new DataQuark(FLD_File, QDType.BOOL));
        }

        public void AddFileQuark(bool fileFlag)
        {
            this.LineSet.Add(new DataQuark(FLD_File, QDType.BOOL, fileFlag));
        }

        public bool GetFileQuark()
        {
            DataQuark tmpQuark = FindQuarkInSet(FLD_File);

            return (tmpQuark != null) ? tmpQuark.BoolValue : false;
        }

        public void AddTypeQuark()
        {
            this.LineSet.Add(new DataQuark(FLD_Type, QDType.INT));
        }

        public void AddTypeQuark(int typeValue)
        {
            this.LineSet.Add(new DataQuark(FLD_Type, QDType.INT, typeValue));
        }

        public int GetTypeQuark()
        {
            DataQuark tmpQuark = FindQuarkInSet(FLD_Type);

            return (tmpQuark != null) ? tmpQuark.IntValue : -1;
        }

        public void AddEnumQuark()
        {
            this.LineSet.Add(new DataQuark(FLD_Enum, QDType.TEXT));
        }

        public void AddEnumQuark(string enumValue)
        {
            this.LineSet.Add(new DataQuark(FLD_Enum, QDType.TEXT, enumValue));
        }

        public string GetEnumQuark()
        {
            DataQuark tmpQuark = FindQuarkInSet(FLD_Enum);

            return (tmpQuark != null) ? tmpQuark.TextValue : string.Empty;
        }

        public DataQuark FindQuarkInSet(string attribName)
        {
            _searchname = attribName;

            return this.LineSet.Find(FindQuarkPred);
        }

        private bool FindQuarkPred(DataQuark readQuark)
        {
            return ((!string.IsNullOrEmpty(_searchname)) && (_searchname.Equals(readQuark.attribName)));
        }
    }

    public class DataQuark
    {
        private string _attribName = string.Empty;
        public string attribName
        {
            get { return _attribName; }
            private set { _attribName = value; }
        }

        public string attribNameReq
        {
            get { return string.Format("@{0}", _attribName); }
        }

        private QDType _dataType = QDType.NotDefine;
        public QDType dataType
        {
            get { return _dataType; }
            private set { _dataType = value; }
        }

        private object _dataValue = new object();
        public object dataValue
        {
            get { return _dataValue; }
            set { _dataValue = value; }
        }

        private bool _callwhere = false;
        public bool callWhere
        {
            get { return _callwhere; }
            set { _callwhere = value; }
        }

        public DataQuark(string isName, QDType isType)
        {
            this.attribName = isName;
            this.dataType = isType;
        }

        public DataQuark(string isName, QDType isType, object isValue)
        {
            this.attribName = isName;
            this.dataValue = isValue;
            this.dataType = isType;
        }

        public DataQuark(string isName, QDType isType, object isValue, bool isWhere)
        {
            this.attribName = isName;
            this.dataValue = isValue;
            this.dataType = isType;
            this.callWhere = isWhere;
        }

        public Guid GuidValue
        {
            get
            {
                Guid guidValue = new Guid();

                if ((this.dataType == QDType.GUID) && (!IsValueEmpty()))
                    Guid.TryParse(this.dataValue.ToString(), out guidValue);

                return guidValue;
            }
        }

        public string TextValue
        {
            get
            {
                return ((this.dataType == QDType.TEXT) && (!IsValueEmpty())) ? this.dataValue.ToString() : string.Empty;
            }
        }

        public bool BoolValue
        {
            get
            {
                return ((this.dataType == QDType.BOOL) && (!IsValueEmpty()) && (this.dataValue.GetType().Equals(typeof(bool)))) ? (bool)this.dataValue : false;
            }
        }

        public int IntValue
        {
            get
            {
                return ((this.dataType == QDType.INT) && (!IsValueEmpty()) && (this.dataValue.GetType().Equals(typeof(int)))) ? (int)this.dataValue : -1;
            }
        }

        public byte[] FileValue
        {
            get
            {
                byte[] fileValue = new byte[] { };

                if ((this.dataType == QDType.BLOB) && (!IsValueEmpty()))
                    try { fileValue = (byte[])this.dataValue; }
                    catch { }

                return fileValue;
            }
        }

        public bool SetNewValue(object newValue)
        {
            if (IsValueEmpty(newValue))
                return false;
            else // need checking by newValue for her type
            {
                this.dataValue = newValue;
                return true;
            }
        }

        public bool IsValueEmpty() { return IsValueEmpty(this.dataValue); }

        public bool IsValueEmpty(object checkValue)
        {
            object emptyValue = new object();

            return ((checkValue == null) || (((checkValue != null)) && ((emptyValue.ToString().Equals(checkValue.ToString())) || (string.IsNullOrEmpty(checkValue.ToString())))));
        }

        public string SelfEqual2Req(bool isOver)
        {
            return this.attribName + "=" + this.attribNameReq + ((!isOver) ? "," : " ");
        }

        public string Attrib2Query(bool? isReq)
        {
            if (isReq == null)
                return string.Format("{0}={1}", this.attribName, this.attribNameReq);
            else
                return ((bool)isReq) ? this.attribNameReq : this.attribName;
        }
    }

    public class ValueQuark
    {
        private int _intvalue = 0;
        public int intValue
        {
            get { return _intvalue; }
            set { _intvalue = value; }
        }

        private Guid _uidvalue = new Guid();
        public Guid uidValue
        {
            get { return _uidvalue; }
            set { _uidvalue = value; }
        }

        private bool _boolvalue = false;
        public bool boolValue
        {
            get { return _boolvalue; }
            set { _boolvalue = value; }
        }

        private string _textvalue = string.Empty;
        public string textValue
        {
            get { return _textvalue; }
            set { _textvalue = value; }
        }

        public ValueQuark(bool boolVal)
        {
            this.boolValue = boolVal;
        }

        public ValueQuark(bool boolVal, string textVal)
        {
            this.boolValue = boolVal;
            this.textValue = textVal;
        }
    }

    public class Charter
    {
        private Guid _findchart = new Guid();

        public string[] chartsGroups
        {
            get { return (from il in this.ChartSet where !string.IsNullOrEmpty(il.chartDir) select il.chartDir).Distinct().ToArray<string>(); }
        }

        public string[] yesNo
        {
            get { return new string[] { "No", "Yes" }; }
        }

        /// <summary> Должно согласовываться с CFType
        /// </summary>
        public string[] fieldsTypes
        {
            get { return new string[] { CFType.NotDefine.ToString(), "DateTime", "Text", "Picklist", "Lookup", "Multilook", "Number", "Double" }; }
        }

        public string[] additionCapts
        {
            get { return new string[] { string.Empty, "Date only: ", string.Empty, "Options: ", "Looked chart field: ", "Linked charts fields: ", string.Empty, "Decimal places: " }; }
        }

        private List<ChartTable> _chartset = new List<ChartTable>();
        public List<ChartTable> ChartSet
        {
            get { return _chartset; }
            set { _chartset = value; }
        }

        public static string GetYesnoText(bool intFlag)
        {
            Charter absChart = new Charter();

            return absChart.yesNo[(intFlag) ? 1 : 0];
        }

        public static string GetYesnoText(int intValue)
        {
            Charter absChart = new Charter();

            if (intValue < 0) intValue = 0;
            else if (intValue > 1) intValue = 1;

            return absChart.yesNo[intValue];
        }

        public static bool GetYesno(string txtValue)
        {
            Charter absChart = new Charter();

            return txtValue == absChart.yesNo[1];
        }

        public static string GetFieldtypeText(CFType fieldType)
        {
            Charter absChart = new Charter();

            return absChart.fieldsTypes[(int)fieldType];
        }

        public static CFType GetFieldtype(string txtValue)
        {
            Charter absChart = new Charter();

            int findIndex = Array.IndexOf(absChart.fieldsTypes, txtValue);

            return (findIndex > 0) ? (CFType)findIndex : CFType.NotDefine;
        }

        public ChartTable GetChartByUid(Guid chartUid)
        {
            _findchart = chartUid;

            return this.ChartSet.Find(PredChartByUid);
        }

        private bool PredChartByUid(ChartTable chartTable)
        {
            return ((!_findchart.Equals(Guid.Empty)) && (_findchart.Equals(chartTable.chartUid)));
        }
    }

    public class ChartTable
    {
        RelayCommand _saveCommand;

        private bool? _chartmake = null;
        public bool? chartMake
        {
            get { return _chartmake; }
            set { _chartmake = value; }
        }

        private Guid _chartuid = new Guid();
        public Guid chartUid
        {
            get { return _chartuid; }
            set { _chartuid = value; }
        }

        private string _picpath = "Pics/ChartIcon.png";
        public string picPath
        {
            get { return _picpath; }
            set { _picpath = value; }
        }

        private string _chartname = string.Empty;
        public string chartName
        {
            get { return _chartname; }
            set 
            { 
                _chartname = value; 
            }
        }

        private string _chartdir = string.Empty;
        public string chartDir
        {
            get { return _chartdir; }
            set { _chartdir = value; }
        }

        private string _filesapp = Charter.GetYesnoText(false);
        public string filesApp
        {
            get { return _filesapp; }
            set { _filesapp = value; }
        }

        public bool readyToSave
        {
            get
            {
                if (this.newItem == null) return false;
                if (!this.picPath.Equals(this.newItem.picPath)) return true;
                if (!this.chartDir.Equals(this.newItem.chartDir)) return true;
                if (!this.filesApp.Equals(this.newItem.filesApp)) return true;
                if (!this.chartName.Equals(this.newItem.chartName)) return true;
                return false;
            }
        }

        public ICommand SaveCommand
        {
            get
            {
                if (_saveCommand == null)
                {
                    _saveCommand = new RelayCommand(
                        param => this.Save(),
                        param => this.readyToSave
                        );
                }
                return _saveCommand;
            }
        }

        private List<ChartField> _fieldset = new List<ChartField>();
        public List<ChartField> FieldSet
        {
            get { return _fieldset; }
            set { _fieldset = value; }
        }

        private List<ChartGroup> _groupset = new List<ChartGroup>();
        public List<ChartGroup> GroupSet
        {
            get { return _groupset; }
            set { _groupset = value; }
        }

        private List<ChartPoint> _pointset = new List<ChartPoint>();
        public List<ChartPoint> PointSet
        {
            get { return _pointset; }
            set { _pointset = value; }
        }

        private ChartTable _newitem = null;
        public ChartTable newItem
        {
            get { return _newitem;}
            set { _newitem = value; }
        }

        public void Save()
        {
            ReadyToEdit();
        }

        public void ReadyToEdit()
        {
            this.newItem = new ChartTable();
            this.newItem.picPath = this.picPath;
            this.newItem.chartDir = this.chartDir;
            this.newItem.filesApp = this.filesApp;
            this.newItem.chartName = this.chartName;
        }

        public void EditIsOver()
        {
            if (this.newItem == null) return;
            if (!this.picPath.Equals(this.newItem.picPath)) this.picPath = this.newItem.picPath;
            if (!this.chartDir.Equals(this.newItem.chartDir)) this.chartDir = this.newItem.chartDir;
            if (!this.filesApp.Equals(this.newItem.filesApp)) this.filesApp = this.newItem.filesApp;
            if (!this.chartName.Equals(this.newItem.chartName)) this.chartName = this.newItem.chartName;
        }

        public ChartTable()
        {
        }
    }

    public class ChartField
    {
        private bool? _chartmake = null;
        public bool? chartMake
        {
            get { return _chartmake; }
            set { _chartmake = value; }
        }

        private Guid _chartuid = new Guid();
        public Guid chartUid
        {
            get { return _chartuid; }
            set { _chartuid = value; }
        }

        private Guid _fielduid = new Guid();
        public Guid fieldUid
        {
            get { return _fielduid; }
            set { _fielduid = value; }
        }

        private string _fieldname = string.Empty;
        public string fieldName
        {
            get { return _fieldname; }
            set { _fieldname = value; }
        }

        private CFType _fieldtype = CFType.NotDefine;
        public CFType fieldType
        {
            get { return _fieldtype; }
            set 
            {
                _fieldtype = value;
                _fieldtypename = Charter.GetFieldtypeText(value);
            }
        }

        private string _fieldtypename = CFType.NotDefine.ToString();
        public string fieldTypeName
        {
            get { return _fieldtypename; }
            set 
            {
                _fieldtype = Charter.GetFieldtype(value);
                _fieldtypename = (_fieldtype != CFType.NotDefine) ? value : _fieldtype.ToString();
            }
        }

        private Guid[] _enumlookups = new Guid[] {};
        public Guid[] EnumLookups
        {
            get { return _enumlookups; }
            set { _enumlookups = value; }
        }

        private string[] _enumoptions = new string[] { };
        public string[] EnumOptions
        {
            get { return _enumoptions; }
            set { _enumoptions = value; }
        }

        private int _subtype = 0;
        public int subType
        {
            get { return _subtype; }
            set { _subtype = value; }
        }

        public string interpretCapt
        {
            get
            {
                string captString = string.Empty;

                switch (this.fieldType)
                {
                    case CFType.PICK: captString = BaseUnit.StringFrOpt(this.EnumOptions);
                        break;
                    case CFType.FRAC: captString = this.subType.ToString();
                        break;
                    case CFType.DATE: captString = Charter.GetYesnoText(this.subType);
                        break;
                    case CFType.LOOK:
                        break;
                    case CFType.MANY:
                        break;
                    default:
                        break;
                }

                return captString;
            }
        }

        public Guid singleLook
        {
            get { return ((this.fieldType == CFType.LOOK) && (this.EnumLookups.Length > 0)) ? this.EnumLookups[0] : new Guid(); }
        }

        public bool readyToSave
        {
            get
            {
                if (this.newItem == null) return false;
                if (this.newItem.fieldType == CFType.NotDefine) return false;
                if (!this.fieldName.Equals(this.newItem.fieldName)) return true;
                if (!this.fieldTypeName.Equals(this.newItem.fieldTypeName)) return true;
                if (!this.EnumLookups.Equals(this.newItem.EnumLookups)) return true;
                if (!this.EnumOptions.Equals(this.newItem.EnumOptions)) return true;
                return false;
            }
        }

        private ChartField _newitem = null;
        public ChartField newItem
        {
            get { return _newitem; }
            set { _newitem = value; }
        }

        public void ReadyToEdit()
        {
            this.newItem = new ChartField();
            this.newItem.fieldName = this.fieldName;
            this.newItem.fieldType = this.fieldType;
            this.newItem.EnumLookups = this.EnumLookups;
            this.newItem.EnumOptions = this.EnumOptions;
        }

        public void EditIsOver()
        {
            if (this.newItem == null) return;
            if (!this.fieldName.Equals(this.newItem.fieldName)) this.fieldName = this.newItem.fieldName;
            if (!this.fieldType.Equals(this.newItem.fieldType)) this.fieldType = this.newItem.fieldType;
            if (!this.EnumLookups.Equals(this.newItem.EnumLookups)) this.EnumLookups = this.newItem.EnumLookups;
            if (!this.EnumOptions.Equals(this.newItem.EnumOptions)) this.EnumOptions = this.newItem.EnumOptions;
        }
    }

    public class ChartGroup
    {
        private Guid _groupuid = new Guid();
        public Guid groupUid
        {
            get { return _groupuid; }
            set { _groupuid = value; }
        }

        private string _groupname = string.Empty;
        public string groupName
        {
            get { return _groupname; }
            set { _groupname = value; }
        }

        private List<ChartPoint> _pointset = new List<ChartPoint>();
        public List<ChartPoint> PointSet
        {
            get { return _pointset; }
            set { _pointset = value; }
        }

        public ChartGroup()
        {
        }
    }

    public class ChartPoint
    {
        private bool? _pointmake = null;
        public bool? pointMake
        {
            get { return (this.isPointGroup) ? true : _pointmake; }
            set { _pointmake = value; }
        }

        private Guid _pointuid = new Guid();
        public Guid pointUid
        {
            get { return _pointuid; }
            set { _pointuid = value; }
        }

        private bool _ispointgrp = false;
        public bool isPointGroup
        {
            get { return _ispointgrp; }
            set { _ispointgrp = value; }
        }

        private string _pointheader = string.Empty;
        public string pointHeader
        {
            get { return _pointheader; }
            set { _pointheader = value; }
        }

        private string _icopath = "Pics/EMPTY.PNG";
        public string icoPath
        {
            get { return _icopath; }
            set { _icopath = value; }
        }

        ChartPoint()
        { }
    }
}